home *** CD-ROM | disk | FTP | other *** search
/ Just Call Me Internet / Just Call Me Internet.iso / prog / atari / c / du_lib / xacc2 / xacc.c < prev    next >
C/C++ Source or Header  |  1994-09-14  |  14KB  |  450 lines

  1. /* XACC.C - Routinen zur Behandlung des XACC-Protokolls
  2.             nach der Spezifikation vom 28. November 1992,
  3.             erweitert um Mag!X 2.0
  4.     (c) 1993 Harald Sommerfeldt @ KI im Maus-Netz
  5.     E-Mail:  Harald_Sommerfeldt@ki.maus.de */
  6.  
  7. /*
  8.     PATCHES FOR LATTICE C [13/9/94] by Craig Graham
  9.     NOTE: If you have Lattice C version 5.5, you cann't use this with
  10.     MultiTOS properly......if you have 5.6, define the symbol __MULTITOS
  11.     to enable the extra stuff.
  12. */
  13.  
  14. /* Geschichte:
  15.     22.03.93: erste Version
  16.     03.08.93: l„uft auch unter Speicherschutz (MiNT)
  17.     05.09.93: berarbeitet und als seperater Quelltext XACC.C
  18.     06.09.93: f„ngt als PRG den fatalen Fehler von Watchdog 1.4 ab, welches im
  19.               Singletasking-Fall als Antwort von ACC_ID f„lschlicherweise
  20.               fleižig ACC_ACC's verschickt, die auch noch eine falsche ID (16)
  21.               enthalten, so daž das AES sich die Kugel gibt, falls man versucht,
  22.               darauf zu antworten :-(((
  23.     09.09.93: - neue Funktion xacc_malloc()
  24.               - die Variable 'xacc' wird nun beachtet
  25.               - Mag!X-Versionsabfrage, um Endlosschleife bei Mag!X 1.x zu verhindern
  26. */
  27.  
  28. /* Hinweise:
  29.     - dieser Quelltext ist Freeware und darf daher nur umsonst und nur
  30.       komplett (XACC.C, XACC.H, XACCTEST.C, XACCTEST.PRJ, XACCTEST.PRG,
  31.       XACC2.TXT) weitergegeben werden!
  32.     - dieser Quelltext kann ohne Hinweis auf mein Copyright in eigene Programme
  33.       nach belieben eingebunden werden, die Entfernung meines Copyrightes in
  34.       diesem Quelltext ist jedoch nicht erlaubt!
  35.     - dieser Quelltext wurde mit Tabweite 3 entwickelt
  36. */
  37.  
  38. #define XACC_ACC
  39. /* Dieses Routinen funktionieren auch, wenn das Programm als ACC l„uft.
  40.     Ist dies bei eigenen Programmen nicht der Fall, so k”nnen die dafr
  41.     zust„ndigen Routinen durch L”schung dieser Zeile ausmaskiert werden,
  42.     um redundanten Quellcode zu vermeiden. */
  43.  
  44. #define XACC_PRG
  45. /* Dieses Routinen funktionieren auch, wenn das Programm als PRG l„uft. */
  46.  
  47. /* #define XACC_RECONLY */
  48. /* Diese Routinen k”nnen nur per XACC empfangen, nicht selber senden.
  49.     Dies ist z.B. sinnvoll, wenn man als ACC das XACC nicht aktiv benutzt,
  50.     d.h. selbst keine Applikationen anmorsen will, man kann aber korrekt
  51.     durch XACC angesprochen werden.
  52.    Das XACC-Protokoll ist hierbei vollst„ndig implementiert!!! */
  53.  
  54.  
  55. #if !defined( XACC_ACC ) && !defined( XACC_PRG )
  56. #error Warum binden Sie diesen Quelltext berhaupt ein?
  57. #endif
  58. #if defined( XACC_SMALL ) && defined( XACC_PRG )
  59. #error XACC_SMALL ist nur bei ACCs m”glich
  60. #endif
  61.  
  62.  
  63. #include <aes.h>
  64. #include <tos.h>
  65. #include <string.h>
  66. #include <stddef.h>
  67. #include "xacc.h"
  68.  
  69. /* ben”tigte AES-Definitionen */
  70. #ifdef __PUREC__
  71. #define ap_version    _GemParBlk.global[0]    /* AES-Versionsnummer (z.B. 0x140 = 1.40) */
  72. #define ap_count        _GemParBlk.global[1]    /* Anzahl der max. laufenden Applikationen */
  73. #define ap_id            _GemParBlk.global[2]    /* eigene ID */
  74. #endif
  75.  
  76. /*
  77.     ++craig [13/9/94]
  78.     Alternative AES definitions to use Lattice C.
  79. */
  80. #ifdef LATTICE
  81. #define ap_version        _AESglobal[0]    /* AES-Version number */
  82. #define ap_count        _AESglobal[1]    /* Maximum number of concurrent applications supported by AES */
  83. #define ap_id            _AESglobal[2]    /* AES application id as returned by appl_init() */
  84. #endif
  85.  
  86.  
  87. /* ben”tigte allgemeine Definitionen */
  88. #define NIL        -1
  89. typedef enum { FALSE, TRUE } bool;
  90.  
  91.  
  92. /* globale Variablen */
  93. static bool xacc;                        /* XACC-Protokoll aktiviert */
  94. static bool xacc_singletask;        /* alte Spezifikation vom 12.3.89 verwenden? */
  95. static char *xacc_name;                /* Platz fr den eigenen XACC-Namen */
  96. static unsigned xacc_groups;        /* eigenes XACC-Group-Wort */
  97. static short xacc_menuid;                /* die ID des Meneshortrages bzw. -1 */
  98.  
  99. #ifndef XACC_SMALL
  100. struct xaccs xaccs[MAX_XACC];        /* Strukturen, um sich die XACC-Partner zu merken */
  101. #endif
  102.  
  103.  
  104. /* XACC-Protokoll initialisieren,
  105.     diese Routine MUSS beim Programmstart irgendwann nach appl_init() aufgerufen werden */
  106.  
  107. short    xacc_init( short menu_id, const char *name, short sizeofname, unsigned groups )
  108. {
  109.     long    value;
  110.     short    i;
  111.  
  112.     xacc = TRUE;
  113.  
  114.     /* den XACC-Namen in einem global zug„nglichen Block (Speicherschutz!) unterbringen */
  115.     xacc_name = xacc_malloc( sizeofname );
  116.     if ( xacc_name == NULL ) return xacc = FALSE;
  117.     memcpy( xacc_name, name, sizeofname );
  118.  
  119.     /* die Men-ID und das Group-Wort merken */
  120.     xacc_menuid = menu_id;
  121.     xacc_groups = groups;
  122.  
  123. #ifndef XACC_SMALL
  124.     /* erstmal alle Eshortr„ge l”schen */
  125.     for ( i = 0; i < MAX_XACC; i++ ) xaccs[i].id = -1;
  126. #endif
  127.  
  128.     /* unter einem Multi-AES-TOS gilt die neue Spezifikation... */
  129.     if ( ap_count != 1 ) {
  130.         xacc_singletask = FALSE;
  131.         /* AES 4.0 (z.B. MTOS) oder MagX 2.x ? */
  132.         if ( ap_version >= 0x400 || (xacc_cookie( 'MagX', &value ) && ((short **)value)[2][24] >= 0x200) ) {
  133.             short    type, id;
  134.             char    name[10];
  135.  
  136.             /* ...wir senden also an alle Applikationen unseren Willkommensgruž */
  137. #ifdef __MULTITOS
  138.             for ( i = appl_search( 0, name, &type, &id ); i; i = appl_search( 1, name, &type, &id ) ) {
  139.                 if ( (type & 6) != 0 ) xacc_id( id, ACC_ID );
  140.             }
  141. #endif
  142.         }
  143.         else xacc = FALSE;        /* sorry, wird wohl nichts draus... */
  144.     }
  145.  
  146.     /* ansonsten handelt es sich um ein altes, trostloses Singletasking-AES,
  147.        wo wir das angestaubte XACC-Protokoll vom 12.3.89 verwenden */
  148.     else xacc_singletask = TRUE;
  149.  
  150.     return xacc;
  151. }
  152.  
  153.  
  154. /*    XACC-Protokoll deinitialisieren,
  155.     diese Routine MUSS irgendwann beim Programmende vor appl_exit() aufgerufen werden */
  156.  
  157. #ifndef XACC_SMALL
  158. void    xacc_exit( void )
  159. {
  160.     short    i;
  161.  
  162.     /* Im Multitasking-Fall ... */
  163.     if ( !xacc_singletask ) {
  164.  
  165.         /* ... verabschieden wir und brav und h”flich (mittels ACC_EXIT) */
  166.         for ( i = 0; i < MAX_XACC; i++ ) {
  167.             if ( xaccs[i].id >= 0 ) xacc_id( xaccs[i].id, ACC_EXIT );
  168.         }
  169.     }
  170.     if ( xacc_name != NULL ) Mfree( xacc_name );
  171. }
  172. #endif
  173.  
  174.  
  175. /* einen globalen (und damit fr XACC geeigneten) Speicherblock allozieren */
  176.  
  177. void    *xacc_malloc( long amount )
  178. {
  179.     void    *result;
  180.  
  181.     if ( ap_version >= 0x0400 && xacc_cookie( 'MiNT', NULL ) )
  182.         result = Mxalloc( amount, 0x0022 );
  183.     else
  184.         result = Malloc( amount );
  185.     return result;
  186. }
  187.  
  188.  
  189. /*    die Nachricht in msgbuf verarbeiten, falls es sich um eine
  190.     Nachricht des Types AC_CLOSE, ACC_ID, ACC_ACC oder ACC_EXIT handelt;
  191.     es wird TRUE zurckgegeben, falls die Nachricht komplett verarbeitet wurde */
  192.  
  193. short    xacc_message( const short *msgbuf )
  194. {
  195.     short    i;
  196.  
  197.     if ( !xacc ) return FALSE;
  198.  
  199. #ifdef XACC_ACC
  200.     if ( msgbuf[0] == AC_CLOSE ) {
  201.  
  202.         /*    wenn wir dem Singletasking-Protokoll h”rig sind,
  203.             ist dies der Moment, wo der Elefant das Wasser l„žt:
  204.             das XACC-Protokoll wird angekurbelt */
  205.         if ( xacc_singletask ) {
  206.  
  207. #ifndef XACC_SMALL
  208.             /* erstmal alle Eshortr„ge l”schen... */
  209.             for ( i = 0; i < MAX_XACC; i++ ) xaccs[i].id = -1;
  210. #endif
  211.  
  212.             /*    ...dann die Lawine in Gang setzen: ACC_ID ans Haupt-
  213.                 programm verschicken; die Bedingung ap_id != 0 sollte
  214.                 hierbei eigentlich immer erfllt sein, aber man weiž
  215.                 ja nie, wer einem so alles eine AC_CLOSE-Nachricht
  216.                 andrehen will (z.B. Schlemi) */
  217.             if ( ap_id != 0 ) xacc_id( 0, ACC_ID );
  218.         }
  219.         return FALSE;
  220.     }
  221. #endif
  222.  
  223.     if ( msgbuf[0] == ACC_ID ) {
  224.  
  225.         /* wenn wir dem Single-Tasking-Protokoll h”rig sind,
  226.             ist dies der Moment, wo der Elefant das Wasser gelassen hat:
  227.             das XACC-Protokoll wurde angekurbelt */
  228.         if ( xacc_singletask ) {
  229. #ifdef XACC_PRG
  230.             if ( ap_id == 0 ) {    /* nur wenn wir ein PRG sind... */
  231.                 short    mymsgbuf[8];
  232.  
  233.                 /* ...verschicken wir fleižig Gružkarten (ACC_ACC) */
  234.                 mymsgbuf[0] = ACC_ACC;
  235.                 mymsgbuf[1] = ap_id;
  236.                 mymsgbuf[2] = 0;
  237.                 mymsgbuf[3] = msgbuf[3];
  238.                 mymsgbuf[4] = msgbuf[4];
  239.                 mymsgbuf[5] = msgbuf[5];
  240.                 mymsgbuf[6] = msgbuf[6];
  241.                 mymsgbuf[7] = msgbuf[1];
  242.                 for ( i = 0; i < MAX_XACC; i++ ) {
  243.                     if ( xaccs[i].id >= 0 ) appl_write( xaccs[i].id, 16, mymsgbuf );
  244.                 }
  245.                 /* dem Ausl”ser dieser Lawine einen Heiratsantrag schicken */
  246.                 xacc_id( msgbuf[1], ACC_ID );
  247.             }
  248. #else
  249.             ;
  250. #endif
  251.         }
  252.  
  253.         /* im Falle des Multitasking-Protokolls tut sich hier nicht
  254.             ganz so viel: Wir erwiedern das Moin (ACC_ID) mit Moin-Moin (ACC_ACC) */
  255.         else xacc_id( msgbuf[1], ACC_ACC );
  256.  
  257. #ifndef XACC_SMALL
  258.         /* auf jeden Fall lassen wir ein ACC_ID nicht ungestraft
  259.             durchgehen, der Absender wird in der Fahndungsliste vermerkt! */
  260.         xacc_remid( msgbuf[1], msgbuf );
  261. #endif
  262.  
  263.         return TRUE;
  264.     }
  265.  
  266.     if ( msgbuf[0] == ACC_ACC ) {
  267.  
  268.         /* ACC_ACC ist vergleichsweise harmlos: Im Singletasking-Fall
  269.             erhalten wir so als ACC von anderen ACCs Kenntnis (und
  270.             vermitteln diesen die Kenntnis ber uns), im Multitasking-Fall
  271.             ist dies einfach das Moin-Moin auf das Moin (ACC_ID)
  272.             ACHTUNG: Im ersten Fall steht die shorteressante Id bei
  273.                      msgbuf[7], im zweiteren bei msgbuf[1]! */
  274.         if ( xacc_singletask ) {
  275. #ifdef XACC_ACC
  276.             if ( ap_id != 0 ) {    /* sollte eigentlich immer der Fall sein,
  277.                                     im Falle Watchdog 1.4 leider nicht :-((( */
  278.                 xacc_id( msgbuf[7], ACC_ID );
  279. #ifndef XACC_SMALL
  280.                 xacc_remid( msgbuf[7], msgbuf );
  281. #endif
  282.             }
  283. #else
  284.             ;
  285. #endif
  286.         }
  287. #ifndef XACC_SMALL
  288.         else xacc_remid( msgbuf[1], msgbuf );
  289. #endif
  290.         return TRUE;
  291.     }
  292.  
  293.     if ( msgbuf[0] == ACC_EXIT ) {
  294.  
  295.         /* Der Untergang der Titanic, hier allerdings nicht ohne
  296.             Vorankndigung: Die Id wird mangels grnen Punkt nicht
  297.             wiederverwertet, sondern wandert auf den Mll */
  298.         xacc_killid( msgbuf[1] );        /* wech mit den Altlasten */
  299.         return TRUE;
  300.     }
  301.  
  302.     return FALSE;
  303. }
  304.  
  305.  
  306. /* ein Teil des Ganzen als XACC-Nachricht versenden
  307.     dest_id : die ap_id des glcklichen Empf„ngers
  308.     message : Nachrichtentyp (ACC_IMG oder ACC_META)
  309.     addr    : Adresse des Speicherblockes
  310.     length  : L„nge des Speicherblockes
  311.     last    : Letzter Speicherblock? (FALSE/TRUE) */
  312.  
  313. short    xacc_send( short dest_id, short message, void *addr, long length, short last )
  314. {
  315.     short    msgbuf[8];
  316.  
  317.     msgbuf[0] = message;
  318.     msgbuf[1] = ap_id;
  319.     msgbuf[2] = 0;
  320.     msgbuf[3] = last;
  321.     *(const char **)(msgbuf+4) = addr;
  322.     *(long *)(msgbuf+6) = length;
  323.     return appl_write( dest_id, 16, msgbuf );
  324. }
  325.  
  326.  
  327. /* ACC_ACK als Antwort auf ACC_TEXT, ACC_KEY, ACC_META oder ACC_IMG versenden
  328.     dest_id : die ap_id des (un-)glcklichen Empf„ngers
  329.     ok      : TRUE oder FALSE */
  330.  
  331. short    xacc_ack( short dest_id, short ok )
  332. {
  333.     short    msgbuf[8];
  334.  
  335.     msgbuf[0] = ACC_ACK;
  336.     msgbuf[1] = ap_id;
  337.     msgbuf[2] = 0;
  338.     msgbuf[3] = ok;
  339.     msgbuf[4] = msgbuf[5] = msgbuf[6] = msgbuf[7] = 0;
  340.     return appl_write( dest_id, 16, msgbuf );
  341. }
  342.  
  343.  
  344. /* die eigene XACC-ID versenden
  345.     dest_id : die ap_id des glcklichen Empf„ngers
  346.     message : ACC_ID oder ACC_ACC, je nach Lust & Laune */
  347.  
  348. short    xacc_id( short dest_id, short message )
  349. {
  350.     short    msgbuf[8];
  351.  
  352.     /* da in xacc_init() die eigene ap_id nicht herausgefiltert wird,
  353.        wird hier verhindert, daž wir uns selber eine Nachricht schicken */
  354.     if ( dest_id != ap_id ) {
  355.         msgbuf[0] = message;            /* Nachrichtentyp */
  356.         msgbuf[1] = ap_id;            /* unsere ap_id */
  357.         msgbuf[2] = 0;                    /* L„nge der Nachricht - 16 */
  358.         msgbuf[3] = xacc_groups;    /* die von uns untersttzten XACC-Gruppen */
  359.         *(const char **)(msgbuf+4) = xacc_name;    /* unser XACC-Name */
  360.         msgbuf[6] = xacc_menuid;    /* unsere Menkennung (falls ACC), sonst -1 */
  361.         msgbuf[7] = NIL;                /* reserviert */
  362.         return appl_write( dest_id, 16, msgbuf );
  363.     }
  364.     return 0;
  365. }
  366.  
  367.  
  368. /* XACC-Eshortrag vermerken (bei ACC_ID & ACC_ACC)
  369.     id     : die ap_id des Absenders,
  370.     msgbuf : der empfangene Nachrichtenpuffer */
  371.  
  372. #ifndef XACC_SMALL
  373. short    xacc_remid( short id, const short *msgbuf )
  374. {
  375.     short    i;
  376.  
  377.     /* eventuell alten Eshortrag mit der gleichen Id vorher l”schen.
  378.        es gibt verschiedene F„lle, wo dies notwendig ist:
  379.        - ein Eshortrag ist veraltet, da das Programm abgestrzt ist
  380.          und daher kein ACC_EXIT versandt hat
  381.        - beim Singletasking-Protokoll kann ein ACC mehrere ACC_ACC
  382.          vom gleichen ACC erhalten
  383.        - beim Multitasking-Protokolls erh„lt ein ACC _IMMER_ von einem
  384.          anderen ACC beim Neustart des Rechners sowohl ein ACC_ID als
  385.          auch ein ACC_ACC
  386.     */
  387.     xacc_killid( id );
  388.  
  389.     /* nun gehts aber los! */
  390.     for ( i = 0; i < MAX_XACC; i++ ) {    /* XACC-Liste abklappern */
  391.         if ( xaccs[i].id < 0 ) {                /* freier Eshortrag gefunden */
  392.             xaccs[i].id = id;                    /* Eshortrag vermerken */
  393.             xaccs[i].groups = msgbuf[3];
  394.             xaccs[i].name = *(const char **)(msgbuf+4);
  395.             return TRUE;
  396.         }
  397.     }
  398.  
  399.     return FALSE;
  400. }
  401. #endif
  402.  
  403.  
  404. /* XACC-Eshortrag l”schen (z.B. bei ACC_EXIT)
  405.     id : die nicht mehr gltige ap_id */
  406.  
  407. #ifndef XACC_SMALL
  408. short    xacc_killid( short id )
  409. {
  410.     short    i;
  411.  
  412.     for ( i = 0; i < MAX_XACC; i++ ) {    /* XACC-Liste abklappern */
  413.         if ( xaccs[i].id == id ) {            /* Id gefunden ! */
  414.             xaccs[i].id = NIL;                /* Eshortrag in der Liste freigeben */
  415.             return TRUE;
  416.         }
  417.     }
  418.  
  419.     return FALSE;
  420. }
  421. #endif
  422.  
  423.  
  424. /* Wert eines Cookies holen, zurckgegeben wird TRUE bei Erfolg */
  425.  
  426. typedef struct {
  427.     long    cookie, value;
  428. } cookiejar;
  429.  
  430. short    xacc_cookie( long cookie, long *value )
  431. {
  432.     cookiejar *_p_cookies;
  433.     void    *sp;
  434.  
  435.     sp = (void *)Super( NULL );
  436.     _p_cookies = *(void **)0x5A0;        /* Zeiger auf Cookiejar holen */
  437.     Super( sp );
  438.     if ( _p_cookies != NULL ) {        /* wenn Cookiejar installiert ... */
  439.                                                 /* ... dann Cookies abklappern ... */
  440.         for (; _p_cookies->cookie != 0L; _p_cookies++ ) {
  441.             if ( _p_cookies->cookie == cookie ) {
  442.                                                 /* ... bis der gewnschte Eshortrag ist */
  443.                 if ( value != NULL ) *value = _p_cookies->value;
  444.                 return TRUE;
  445.             }
  446.         }
  447.     }
  448.     return FALSE;
  449. }
  450.